package com.itheima.d6_tcp3;

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.Socket;

public class ServerReaderThread extends Thread{
    //2.通过有参构造器接到socket通信管道后，应该定义一个变量来记住这个管道
    private Socket socket;

    //1.定义一个有参构造器，接到当前客户端发过来的socket通信管道
    public ServerReaderThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            //从socket通信管道中得到一个字节输入流。
            InputStream is = socket.getInputStream();   //有异常，直接try catch
            //包装成数据输入流
            DataInputStream dis = new DataInputStream(is);
            //让这个线程去不断地读当前创建的客户端socket管道发过来的信息
            while (true){
                /*
                   String msg = dis.readUTF();
                   System.out.println(msg);
怎么读取客户端下线关闭的消息，分析：
            1.客户端正常发送消息，然后执行完输出msg，因为没有进行try catch捕获，所以紧接着就会执行dos.close();socket.close();
            从而导致报错：java.net.SocketException: Socket closed

            2.客户端调用这两个方法的时候dos.close();socket.close();，说明这个客户端就要下线了
            那么dis.readUTF就会出现异常，所以需要对这段代码进行try catch异常拦截处理
                 */
                //上面代码改造如下：
                try {
                    //使用数据输入流读取客户端发送过来的消息
                    String msg = dis.readUTF();
                    System.out.println(msg);

                } catch (Exception e) {
                    //这个socket通信管道对应的线程在这里拦截到了异常，那说明客户端那边已经关闭了管道就是下线了
                    System.out.println("有人下线了：" + socket.getRemoteSocketAddress());
                    //客户端下线了，那么服务端的这个线程占用的资源也要释放掉
                    dis.close();
                    socket.close();
                    //并且跳出这个循环，线程也就挂掉了
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
